Abraxus's Blog

RaRCTF Very TriVial ReVersing Write Up

Details:

Jeopardy style CTF

Category: Reverse Engineering

Points: 300

Comments: Hey, at least it's not Haskell!

Write up:

Looking into the main function of the program I saw a call to a function called main__main:

__int64 main__main()
{
  __int64 v0;
  __int64 result; 
  __int64 v2[4]; 
  __int64 v3[2]; 

  v2[2] = (__int64)L_1252;
  v2[3] = 0x10000000ELL;
  v2[0] = os__input(L_1252, 0x10000000ELL);
  v2[1] = v0;
  memmove_plt(v3, v2, 16LL);
  result = (unsigned __int8)main__check(v3[0], v3[1]);
  if ( (_BYTE)result )
    result = println(L_1254, 0x100000003LL);
  return result;
}

This function read the user input into v2 as a pointer and then called main__check:

__int64 __fastcall main__check(__int64 a1, __int64 a2)
{
  int v2; 
...
  __int64 v57;

  v56 = a1;
  v57 = a2;
  _new_array_with_default(v54, 0LL, 0LL, 1LL, 0LL);
  memmove_plt(v55, v54, 32LL);
  v51[0] = 19;
  v51[1] = 55;
  new_array_from_c_array(v52, 2LL, 2LL, 4LL, v51);
  memmove_plt(v53, v52, 32LL);
  for ( i = 0; i < (int)v57; ++i ) // loop through the length of the input
  {
    v49 = *(_BYTE *)(i + v56);
    v47 = &v29;
    memmove_plt(&v29, v53, 32LL);
    v6 = (_DWORD *)array_get(0, (unsigned int)v53, v2, v3, v4, v5, v29, v30, v31); // get a value
    v46 = *v6 ^ v49; // xor that value
    v47 = &v29;
    memmove_plt(&v29, v53, 32LL);
    v11 = (_DWORD *)array_get(1, (unsigned int)v53, v7, v8, v9, v10, v29, v30, v31); // get another value
    v48 = *v11 + v46; // add that value
    array_push(v55, &v48);
    v47 = &v29;
    memmove_plt(&v29, v53, 32LL);
    v44[0] = *(_DWORD *)array_get(1, (unsigned int)v53, v12, v13, v14, v15, v29, v30, v31);
    v47 = &v29;
    memmove_plt(&v29, v53, 32LL);
    v44[1] = *(_DWORD *)array_get(0, (unsigned int)v53, v16, v17, v18, v19, v29, v30, v31);
    new_array_from_c_array(v45, 2LL, 2LL, 4LL, v44); // swap the locations of the two values
    memmove_plt(v53, v45, 32LL);
  }
  memmove_plt(v41, v55, 32LL);
  v40 = v43;
  _new_array(v38, 0LL, v43, 4LL);
  memmove_plt(v39, v38, 32LL);
  for ( j = 0; j < v40; ++j )
  {
    v36 = *(_BYTE *)(j + v42);
    v35 = anon_fn_e2d96d4126f6333f_byte__int_215(v36);
    array_push(v39, &v35);
  }
  v33[0] = 152; // create encrypted flag
  v33[1] = 105;
  v33[2] = 152;
  v33[3] = 103;
  v33[4] = 158;
  v33[5] = 100;
  v33[6] = 159;
  v33[7] = 119;
  v33[8] = 173;
  v33[9] = 101;
  v33[10] = 118;
  v33[11] = 118;
  v33[12] = 178;
  v33[13] = 105;
  v33[14] = 158;
  v33[15] = 115;
  v33[16] = 169;
  v33[17] = 87;
  v33[18] = 180;
  v33[19] = 35;
  v33[20] = 158;
  v33[21] = 119;
  v33[22] = 179;
  v33[23] = 146;
  v33[24] = 169;
  v33[25] = 88;
  v33[26] = 174;
  v33[27] = 45;
  v33[28] = 89;
  v33[29] = 101;
  v33[30] = 168;
  v33[31] = 21;
  v33[32] = 89;
  v33[33] = 33;
  v33[34] = 173;
  v33[35] = 102;
  v33[36] = 165;
  new_array_from_c_array(v34, 37LL, 37LL, 4LL, v33);
  v47 = &v29;
  memmove_plt(&v29, v34, 32LL);
  v47 = &v25;
  memmove_plt(&v25, v39, 32LL);
  if ( !(unsigned __int8)Array_int_arr_eq(
                           (unsigned int)&v25,
                           (unsigned int)v39,
                           v20,
                           v21,
                           v22,
                           v23,
                           v25,
                           v26,
                           v27,
                           v28,
                           v29,
                           v30,
                           v31) ) // check the flag
    return 0LL;
  v32 = 1;
  return 1LL;
}

The program went through the entire input we had and xor'ed it by a, then added by b, then swapped a and b for the next one. From this I made the following script:

# encrypted flag
x = [152, 105, 152, 103, 158, 100, 159, 119, 173, 101, 118, 118, 178, 105, 158, 115, 169, 87, 180, 35, 158, 119, 179, 146, 169, 88, 174, 45, 89, 101, 168, 21, 89, 33, 173, 102, 165]

# a and b
a = 0x13
b = 0x37

s = ""

# go through length of encrypted bytes
for i in range(len(x)):

    # subtract b and xor a
	s += chr(0xFF & ((x[i] - b) ^ a))

    # swap a and b
	c = a
	a = b
	b = c

# print flag
print(s)

Once run I got:

rarctf{See,ThatWasn'tSoHard-1eb519ed}